import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'dart:convert';
import '../../models/user_model.dart';
import 'dart:io';
import 'dart:typed_data';

/// 认证本地数据源
class AuthLocalDataSource {
  static const String _tokenKey = 'auth_token';
  static const String _refreshTokenKey = 'refresh_token';
  static const String _userInfoKey = 'user_info';
  static const String _isLoggedInKey = 'is_logged_in';

  // 安全存储（用于敏感数据如Token）
  final FlutterSecureStorage _secureStorage = const FlutterSecureStorage(
    aOptions: AndroidOptions(
      encryptedSharedPreferences: true,
    ),
    iOptions: IOSOptions(
      accessibility: KeychainAccessibility.first_unlock_this_device,
    ),
  );

  // Hive存储（用于非敏感数据）
  late Box _authBox;
  bool _isBoxOpen = false;
  bool _isHiveInitialized = false;

  /// 检查Box是否已打开
  bool get isBoxOpen => _isBoxOpen;

  /// 关闭Box
  Future<void> close() async {
    if (_isBoxOpen) {
      try {
        await _authBox.close();
        _isBoxOpen = false;
        print('Box已关闭');
      } catch (e) {
        print('关闭Box时出错: $e');
      }
    }
  }

  /// 初始化
  Future<void> initialize() async {
    if (_isBoxOpen) return;

    try {
      // 确保Hive已初始化
      if (!_isHiveInitialized) {
        await Hive.initFlutter();
        _isHiveInitialized = true;
      }

      // 检查Box是否已打开
      if (Hive.isBoxOpen('auth')) {
        _authBox = Hive.box('auth');
        _isBoxOpen = true;
        print('使用已打开的auth box');
      } else {
        _authBox = await _openBoxWithRetry('auth');
        _isBoxOpen = true;
        print('打开新的auth box');
      }
      print('本地数据源初始化完成，Box状态: $_isBoxOpen');
    } catch (e) {
      print('Hive initialization failed: $e');
      // 如果Hive初始化失败，使用内存存储作为后备方案
      try {
        _authBox = await _openBoxWithRetry('auth', useMemory: true);
        _isBoxOpen = true;
        print('使用内存存储作为后备方案');
      } catch (innerE) {
        print('Memory storage initialization failed: $innerE');
        rethrow;
      }
    }
  }

  /// 带重试机制的打开Box方法
  Future<Box> _openBoxWithRetry(String name, {bool useMemory = false}) async {
    int attempts = 0;
    const maxAttempts = 5;
    while (attempts < maxAttempts) {
      try {
        if (useMemory) {
          return await Hive.openBox(name, bytes: Uint8List(0));
        } else {
          // 检查Box是否已经打开
          if (Hive.isBoxOpen(name)) {
            return Hive.box(name);
          }
          return await Hive.openBox(name);
        }
      } catch (e) {
        if (e is PathAccessException) {
          attempts++;
          print('Hive PathAccessException (尝试 $attempts/$maxAttempts): $e');
          if (attempts >= maxAttempts) {
            // 如果所有重试都失败了，使用内存存储
            print('所有重试都失败了，使用内存存储');
            return await Hive.openBox(name, bytes: Uint8List(0));
          }
          // 等待一段时间后重试，增加延迟时间
          await Future.delayed(Duration(milliseconds: 200 * attempts));
        } else {
          print('Hive打开Box时发生其他错误: $e');
          rethrow;
        }
      }
    }
    // 如果所有重试都失败了，使用内存存储
    return await Hive.openBox(name, bytes: Uint8List(0));
  }

  /// 保存登录信息
  Future<void> saveLoginData({
    required String token,
    required String refreshToken,
    required UserInfo userInfo,
  }) async {
    if (!_isBoxOpen) await initialize();
    print(
        '保存登录数据: token=$token, refreshToken=$refreshToken, userInfo=$userInfo');
    await _secureStorage.write(key: _tokenKey, value: token);
    await _secureStorage.write(key: _refreshTokenKey, value: refreshToken);
    await _authBox.put(_userInfoKey, userInfo.toJson());
    await _authBox.put(_isLoggedInKey, true);
    // 确保数据已写入磁盘
    await _authBox.flush();
    print('登录数据保存完成');
    print('保存后Box中的所有键: ${_authBox.keys}');
  }

  /// 获取访问Token
  Future<String?> getToken() async {
    if (!_isBoxOpen) await initialize();
    return await _secureStorage.read(key: _tokenKey);
  }

  /// 获取刷新Token
  Future<String?> getRefreshToken() async {
    if (!_isBoxOpen) await initialize();
    return await _secureStorage.read(key: _refreshTokenKey);
  }

  /// 保存新的访问Token
  Future<void> saveToken(String token) async {
    if (!_isBoxOpen) await initialize();
    await _secureStorage.write(key: _tokenKey, value: token);
  }

  /// 获取用户信息
  Future<UserInfo?> getUserInfo() async {
    if (!_isBoxOpen) await initialize();
    try {
      print('尝试从本地存储获取用户信息');
      print('当前Box中的所有键: ${_authBox.keys}');
      final userInfoJson = _authBox.get(_userInfoKey);

      print('本地存储中的用户信息: $userInfoJson');
      print('本地存储中用户信息的类型: ${userInfoJson?.runtimeType}');

      if (userInfoJson != null) {
        // 安全地转换为Map<String, dynamic>
        Map<String, dynamic> convertedJson;
        if (userInfoJson is Map) {
          convertedJson = userInfoJson.map<String, dynamic>(
              (key, value) => MapEntry(key.toString(), value));
        } else if (userInfoJson is String) {
          // 如果是字符串，尝试解析为JSON
          convertedJson = Map<String, dynamic>.from(json.decode(userInfoJson));
        } else {
          print('未知的用户信息格式: ${userInfoJson.runtimeType}');
          return null;
        }
        final userInfo = UserInfo.fromJson(convertedJson);
        print('解析后的用户信息: $userInfo');
        return userInfo;
      }
      print('本地存储中没有用户信息');
      return null;
    } catch (e) {
      print('获取用户信息时发生错误: $e');
      // 处理可能的解析错误
      return null;
    }
  }

  /// 保存用户信息
  Future<void> saveUserInfo(UserInfo userInfo) async {
    if (!_isBoxOpen) await initialize();
    await _authBox.put(_userInfoKey, userInfo.toJson());
  }

  /// 设置登录状态
  Future<void> setLoggedInStatus(bool isLoggedIn) async {
    if (!_isBoxOpen) await initialize();
    await _authBox.put(_isLoggedInKey, isLoggedIn);
  }

  /// 检查是否已登录
  Future<bool> isLoggedIn() async {
    if (!_isBoxOpen) await initialize();
    try {
      print('检查登录状态时Box中的所有键: ${_authBox.keys}');
      final token = await getToken();
      final isLoggedIn =
          _authBox.get(_isLoggedInKey, defaultValue: false) as bool;
      print('Token: $token, isLoggedIn: $isLoggedIn');
      return token != null && isLoggedIn;
    } catch (e) {
      // 处理可能的错误
      return false;
    }
  }

  /// 清除所有认证数据
  Future<void> clearAuthData() async {
    if (!_isBoxOpen) await initialize();
    print('清除认证数据前Box中的所有键: ${_authBox.keys}');
    try {
      await _secureStorage.delete(key: _tokenKey);
    } catch (e) {
      // 静默处理错误
    }

    try {
      await _secureStorage.delete(key: _refreshTokenKey);
    } catch (e) {
      // 静默处理错误
    }

    try {
      await _authBox.delete(_userInfoKey);
    } catch (e) {
      // 静默处理错误
    }

    try {
      await _authBox.put(_isLoggedInKey, false);
    } catch (e) {
      // 静默处理错误
    }
    print('清除认证数据后Box中的所有键: ${_authBox.keys}');
  }

  /// 清除所有数据
  Future<void> clearAll() async {
    if (!_isBoxOpen) await initialize();
    try {
      await _secureStorage.deleteAll();
    } catch (e) {
      // 静默处理错误
    }

    try {
      await _authBox.clear();
    } catch (e) {
      // 静默处理错误
    }
  }

  /// 检查Token是否即将过期
  Future<bool> isTokenExpiringSoon() async {
    if (!_isBoxOpen) await initialize();
    // 这里可以添加Token过期检查逻辑
    // 目前简单返回false，实际应用中可以解析JWT Token的过期时间
    return false;
  }

  /// 获取用户设置
  Future<Map<String, dynamic>?> getUserSettings() async {
    if (!_isBoxOpen) await initialize();
    return _authBox.get('user_settings') as Map<String, dynamic>?;
  }

  /// 保存用户设置
  Future<void> saveUserSettings(Map<String, dynamic> settings) async {
    if (!_isBoxOpen) await initialize();
    await _authBox.put('user_settings', settings);
  }

  /// 获取应用版本
  String? getAppVersion() {
    if (!_isBoxOpen) return null;
    return _authBox.get('app_version') as String?;
  }

  /// 保存应用版本
  Future<void> saveAppVersion(String version) async {
    if (!_isBoxOpen) await initialize();
    await _authBox.put('app_version', version);
  }

  /// 获取语言设置
  String getLanguage() {
    if (!_isBoxOpen) return 'zh';
    return _authBox.get('language', defaultValue: 'zh') as String;
  }

  /// 保存语言设置
  Future<void> saveLanguage(String language) async {
    if (!_isBoxOpen) await initialize();
    await _authBox.put('language', language);
  }

  /// 获取主题模式
  String getThemeMode() {
    if (!_isBoxOpen) return 'system';
    return _authBox.get('theme_mode', defaultValue: 'system') as String;
  }

  /// 保存主题模式
  Future<void> saveThemeMode(String themeMode) async {
    if (!_isBoxOpen) await initialize();
    await _authBox.put('theme_mode', themeMode);
  }
}
